//`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module MutMosi32(
	input				clk_in,//100M时钟
	input				rst_n,
	input				wr_en,
	output	reg			CS,
	output	reg			SPI_SCLK,
	input				SPI_SDI,
	output	reg			SPI_SDO,

	input		[15:0]	CMD , //读数地址
	output	reg	[31:0]	DATA1, //数据1
	output	reg	[31:0]	DATA2  //数据1
);

localparam READY		= 4'd1;
localparam IDLE         = 4'd2;
localparam data_CMD     = 4'd3;
localparam SCLK_L       = 4'd4;
localparam data_DATA1   = 4'd5;
localparam data_DATA2   = 4'd6;
localparam OVER1        = 4'd7;
localparam OVER         = 4'd8;

always @(posedge clk_in or negedge rst_n) begin
	if (!rst_n) begin
		state	<= IDLE;
	end else begin
		case (state)
			IDLE: begin
				if (wr_pos) begin
					state	<= READY;
				end else begin
					state	<= IDLE;
				end
			end
			READY: begin
				if (cnt_wr == 4'h1) begin
					state	<= WRITE1;
				end else begin
					state	<= READY;
				end
			end
			WRITE1: begin
				if (cnt_wr == 4'h2) begin
					state	<= WRITE2;
				end else begin
					state	<= WRITE1;
				end
			end
			WRITE2: begin
				if (cnt_wr == 4'h3) begin
					state	<= WRITE3;
				end else begin
					state	<= WRITE2;
				end
			end
			WRITE3: begin
				if (cnt_wr == 4'h4) begin
					state	<= WRITE4;
				end else begin
					state	<= WRITE3;
				end
			end
			WRITE4: begin
				if (cnt_wr == 4'h5) begin
					state	<= IDLE;
				end else begin
					state	<= WRITE4;
				end
			end
			default: ;
		endcase
	end
end

always @(posedge clk_in or negedge rst_n) begin
	if (!rst_n) begin
		
	end else begin
		case (state)
			IDLE: begin
				spi_cs	<= 1'b1;
				spi_clk	<= 1'b0;
				spi_sdo	<= 8'h0;
			end
			READY: begin
				spi_cs	<= 1'b0;
				spi_clk	<= ~spi_clk;
				spi_sdo	<= 8'h0;
			end
			WRITE1: begin
				spi_cs	<= 1'b0;
				spi_clk	<= ~spi_clk;
				spi_sdo	<= wr_data[7:0];
			end
			WRITE2: begin
				spi_cs	<= 1'b0;
				spi_clk	<= ~spi_clk;
				spi_sdo	<= wr_data[15:8];
			end
			WRITE3: begin
				spi_cs	<= 1'b0;
				spi_clk	<= ~spi_clk;
				spi_sdo	<= wr_data[23:16];
			end
			WRITE4: begin
				spi_cs	<= 1'b0;
				spi_clk	<= ~spi_clk;
				spi_sdo	<= wr_data[31:24];
			end
			default: ;
		endcase
	end
end

always @(posedge spi_clk or negedge rst_n) begin
	if (!rst_n) begin
		
	end else begin
		if (cnt_wr < 4'h6) begin
			cnt_wr	<= cnt_wr + 1'b1;
		end else begin
			cnt_wr	<= 4'h0;
		end
	end
end

reg[3:0] state;
reg[1:0] cnt_4;
reg[7:0] cnt_CMD;
reg[7:0] cnt_data1;
reg[7:0] cnt_data2;
reg[7:0] cnt_OVER1;

reg[31:0] DATA11;
reg[31:0] DATA22;
reg[4:0] cnt_8;
reg[4:0] cnt_5;
reg[7:0] SCLK_LL;

always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
		cnt_8	<= 5'd0;
	else if(cnt_8 == 'd5)
		cnt_8	<= cnt_8;
	else if(state == IDLE)
		cnt_8	<= cnt_8 + 1'b1;
	else
		cnt_8	<= 5'd0;
end

reg en_0,en_1;
wire en_pos;
//wire en_neg;
always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
	begin
		{en_1,en_0} <= 2'b00;
	end
	else
	begin
		{en_1,en_0} <= {en_0,rd_en};
	end
end

assign en_pos = ((~en_1) & (en_0)) ? 1'b1 : 1'b0;  /* 取上升沿 */
//assign en_neg = ((~en_0) & (en_1)) ? 1'b1 : 1'b0;  /* 取下降沿 */
always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
	begin
		CS		<= 1;
		DATA11	<= 0;
		DATA22	<= 0;
		state	<= READY;
		cnt_5	<= 0;
		cnt_CMD	<= 'd15;
		cnt_data1<= 'd33;
		cnt_data2<= 'd31;
		cnt_OVER1<= 'd5;
		SPI_SDO	<= 0;
		SCLK_LL	<= 0;
	end
	else
	begin
		case(state)
		READY:begin
			if(en_pos)
			begin
				CS		<= 0;
				state	<= IDLE;
				DATA11  <= 0;
				DATA22  <= 0;
				SPI_SDO <= 0;
				SCLK_LL <= 0;
			end
			else
			begin
				CS		<= 1;
				state	<= READY;
				DATA11  <= 0;
				DATA22  <= 0;
				SPI_SDO <= 0;
			end
		end
		IDLE:begin
			if(cnt_8 == 'd5)
			begin
				state		<= data_CMD;
				cnt_CMD	 	<= 'd15;
				cnt_data1 	<= 'd33;
				cnt_data2 	<= 'd31;
				cnt_OVER1 	<= 'd5;
				SPI_SDO	 	<= 0;
			end
		end
		data_CMD:begin
			if(cnt_4 == 'd0)
			begin
				CS <= 0;
				if(cnt_CMD > 'd0)
				begin
					SPI_SDO <= CMD[cnt_CMD];
					cnt_CMD <= cnt_CMD - 8'd1;
				end
				else
				begin
					SPI_SDO <= CMD[0];
					state 	<= SCLK_L;
				end
			end
		end
		SCLK_L:begin
			if(SCLK_LL > 'd20)
			begin
				SCLK_LL <= 0;
				state 	<= data_DATA1;
				CS 		<= 0;
			end
			else if(SCLK_LL == 'd4)
			begin
				state 	<= SCLK_L;
				SCLK_LL <= SCLK_LL + 8'd1;
				CS 		<= 0;
				SPI_SDO <= 0;
			end
			else
			begin
				CS		<= 0;
				SCLK_LL <= SCLK_LL + 8'd1;
				state	<= SCLK_L;
			end
		end
		data_DATA1:begin
			if(cnt_4 == 'd2)
			begin
				CS	<= 0;
				if(cnt_data1 > 'd0)
				begin
					DATA11[cnt_data1] <= SPI_SDI;
					cnt_data1 <= cnt_data1 - 8'd1;
				end
				else
				begin
					DATA11[0] <= SPI_SDI;
					state <= data_DATA2;
				end
			end
		end
		data_DATA2:begin
			if(cnt_4 == 'd2)
			begin
				CS	<= 0;
				if(cnt_data2 > 'd0)
				begin
					DATA22[cnt_data2] <= SPI_SDI;
					cnt_data2 <= cnt_data2 - 8'd1;
					DATA1 <= DATA11;
				end
				else
				begin
					DATA22[0]<= SPI_SDI;
					state	<= OVER1;
				end
			end
		end
		OVER1:begin
			if(cnt_4 == 'd2)
			begin
				CS	<= 0;
				if(cnt_OVER1 > 'd0)
				begin
					DATA2	<= DATA22;
					cnt_OVER1<= cnt_OVER1 - 8'd1;
				end
				else
				begin
					state	<= OVER;
					CS		<= 0;
				end
			end
		end
		OVER:begin
			if(cnt_5 == 'd4)
			begin
				CS		<= 1;
				state	<= READY;
				cnt_5	<= 0;
			end
			else
			begin
				cnt_5	<= cnt_5 + 5'd1;
				CS		<= 0;
				state	<= state;
			end
		end

		default:begin
			state	<= READY;
			DATA11	<= 0;
			DATA22	<= 0;
			CS		<= 1;
			SPI_SDO	<= 0;
		end

		endcase
	end
end

always@(posedge clk_in or negedge rst_n)
begin
    if(!rst_n)
        SPI_SCLK	<= 1'b0;
    else if(cnt_4 == 'd0)
        SPI_SCLK	<= 1'b1;
    else if(cnt_4 == 'd2)
        SPI_SCLK	<= 1'b0;
    else
        SPI_SCLK	<= SPI_SCLK;
end

always@(posedge clk_in or negedge rst_n)
begin
	if(!rst_n)
		cnt_4	<= 'd2;
	else if(state == data_CMD )
		cnt_4	<= cnt_4 + 1'b1;
	else if(state == SCLK_L )
		cnt_4	<= 'd2;
	else if(state == data_DATA1 )
		cnt_4	<= cnt_4 + 1'b1;
	else if(state == data_DATA2)
		cnt_4	<= cnt_4 + 1'b1;
	else if(state == OVER1 )
		cnt_4	<= cnt_4 + 1'b1;
	else
		cnt_4	<= 'd2;
end

endmodule

